<?php
declare (strict_types = 1);

namespace app\user\model;

use app\api\model\WXBizDataCrypt;
use app\common\model\Config;
use app\myself\Bc;
use app\order\model\Order;
use think\facade\Db;
use think\facade\Log;
use think\Model;

/**
 * @mixin \think\Model
 */
class User extends Model
{
    //
    public $page = '';//分页数据
    public $count = '';//数据总数
    public $error = '';//数据总数

    public function getAvatarurlAttr($value)
    {
        //return strpos($value,'http') >= 0 ? $value : env('app.host_domin').'://'.env('app.static_host').$value;
        return getHostDominUrl($value);
    }

    /*
     * 获取用户头像昵称
     */
    public function getUserInfoById($id){
        try{
            if(empty($id)) exception('找不到该用户!');
            $info = $this->field('id,nickname,avatarurl')->where(['id'=>$id,'is_delete'=>0])->find();
            return !empty($info)?$info:[];
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /*
     * 获取小程序授权信息
     */
    public function updateUserInfo($user){
        try{
            if(empty($user)) exception('找不到该用户!');
            $data = Input('post.');
            $mod = new Config();
            $config =  $mod->toData('wechat');
            if(empty($user['session_key']))
                exception('微信登录信息丢失!');
            $WX = new WXBizDataCrypt($config['appid'], $user['session_key']);
            $errCode = $WX->decryptData($data['encryptedData'],$data['iv'],$ret );
            if($errCode>0) exception($errCode);
            $ret = !empty($ret)? json_decode($ret,true) : [];
            if(empty($ret))  exception('获取授权数据失败,请重试!');
            $userData = [
                'id'=>$user['id'],
                'openid'=>$ret['openId'],
                'unionid'=>$ret['unionId'],
                'nickname'=>$ret['nickName'],
                'avatarurl'=>$ret['avatarUrl'],
            ];
            $userInfoData = [
                'country'=>$ret['country'],
                'province'=>$ret['province'],
                'city'=>$ret['city'],
                'gender'=>$ret['gender'],
            ];
            $this::startTrans();
            $this->update($userData);//更新user表
            Db::name('user_info')->where('uid',$user['id'])->update($userInfoData);//更新user_info表
            $this::commit();
            return true;
        }catch (\Exception $e){
            $this::rollback();
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /**
     * 登录code拿到用户的openid和key 返回token
     */
    public function loginCode($info)
    {
        try{
            $time =  time();
            $session_key = $info['session_key'];
            $openid = $info['openid'];
            // 生成token
            $token = createToken($openid);
            $count = $this->where('openid', $openid)->count();
            // 如果有用户存在
            if($count > 0){
                // 更新key并且  更新最后上线时间
                $user = $this->where('openid', $openid)->find();
                if(!empty($user)&&$user['is_delete'] == 1) exception('用户信息异常，请联系客服！');
                $user->session_key = $session_key;
                $user->last_time = $time;
                $user->save();
                $data = $user->toArray();
                unset($data['unionid']);
            }else{
                $data = [
                    'avatarurl' => 'https://miaommeis-1301812909.cos.ap-guangzhou.myqcloud.com/icon/%E7%BC%96%E7%BB%84%205%402x.png',
                    'nickname' => '美妆说',
                    'invite_code' => $this->getInvite(),
                    'openid' => $openid,
                    'session_key' => $session_key,
                    'token' => $token,
                    'last_time' => $time,
                    'add_time' => $time,
                ];
                $modelFlag = $this->insertGetId($data);
                if(!$modelFlag) exception('登录异常，请重新尝试！');
                $wallet = Db::name('user_wallet')->insertGetId(['uid'=>$modelFlag]);
                $info = Db::name('user_info')->insertGetId(['uid'=>$modelFlag, 'last_ip'=>$_SERVER['REMOTE_ADDR'], 'last_time'=>$time]);
                $info = Db::name('user_invite')->insertGetId(['uid'=>$modelFlag, 'add_time'=>$time]);
                $data['id'] = $modelFlag;
            }
            $data['nickName'] = $data['nickname']??'美妆说';
            $data['token'] = $token;
            unset($data['openid']);
            unset($data['session_key']);
            $redis = getRedis();
            #将token存入redis 时间3600秒
            $redis->set("token:{$token}", $data['id'], 3600*24);
            return $data;
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /*
     * 获取小程序授权手机号绑定
     */
    public function bindingPhone($id){
        try{
            if(empty($id)) exception('找不到该用户!');
            $data = Input('post.');
            $mod = new Config();
            $config =  $mod->toData('wechat');
            $user = $this->where(['id'=>$id,'is_delete'=>0])->find();
            if(!empty($user['phone'])) exception('手机号已绑定!');
            if(empty($user['session_key'])) exception('微信登录信息丢失!');
            $WX = new WXBizDataCrypt($config['appid'], $user['session_key']);
            $errCode = $WX->decryptData($data['encryptedData'],$data['iv'],$ret );
            if($errCode>0)
                exception($errCode);
            $ret = !empty($ret)? json_decode($ret,true) : [];
            if(empty($ret))  exception('获取授权数据失败,请重试!');
            if(empty($ret['purePhoneNumber'])) exception('手机号不能为空');
            if(!preg_match("/^1[3456789]\d{9}$/", $ret['purePhoneNumber']))
                exception('请使用中国大陆手机号码进行绑定');
            //保存手机号并提升用户等级
            $this->update(['id'=>$user['id'],'phone'=>$ret['purePhoneNumber'],'level'=>1]);
            return ['phone'=>$ret['purePhoneNumber']];
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /*
     * 获取邀请码
     */
    public function getInvite(){
        $str = 'QWERTYUIOPASDFGHJKLZXCVBNM0123456789';
        $len = strlen($str);
        $inviteCode = '';
        for($i=0;$i<7;$i++){
            $position = mt_rand(0,$len-1);//字符串节点
            $inviteCode .= substr($str,$position,1);
        }
        if($this->where(['invite_code'=>$inviteCode])->find())
            $this->getInvite();

        return $inviteCode;
    }

    /*
     * 获取用户详情&订单数据
     */
    public function getInfo($user){
        try{
            if(empty($user)) exception('找不到该用户!');
            $where = ['uid' => $user->id, 'is_delete'=>0];
            $field = 'balance,volume_balance as volume_num';
            $item = (new UserWallet())->where($where)->field($field)->find();
            $info = empty($item) ? array():$item->toArray();
            $info['invite_num'] = $this->getInviteNum($user->id);
            $info = array_merge($info,$user->toArray());
            if(empty($info['phone'])){
                $info['volume_num'] = 0;
                $info['balance'] = 0;
                $info['level'] = '游客';
            }else{
                $level = (new UserLevel())->getLevelForId($info['level']);//获取用户等级名称
                $info['level'] = isset($level['name'])?$level['name']:'游客';
            }
            $info['balance'] = $info['balance']>0 ? getformat($info['balance']) : $info['balance'];
            $info['volume_num'] = $info['volume_num']>0 ? getformat($info['volume_num']) : $info['volume_num'];
            $info['nickname'] = $info['nickName'];
            $info['is_visitor'] = $info['phone']?1:0;
            $info['is_binding'] = $info['invite_id']?1:0;

            return $info;
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /*
     * 获取邀请人信息
     */
    public function checkInviteCode($id){
        try{
            if(empty($id)) exception('找不到该用户!');
            $code = Input('post.code');
            if(empty($code))
                exception('邀请码不能为空!');
            $user = $this->field('nickname,level')->where(['invite_code'=>$code,'is_delete'=>0])->find();
            if(!$user)
                exception('该用户不存在!');
            $res = $this->field('level')->where(['id'=>$id,'is_delete'=>0])->find();
            if($res['level'] > $user['level'])
                exception('该邀请人等级过低!');
            return $user['nickname'];
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /*
     * 绑定邀请人
     */
    public function bindInviteCode($user){
        try{
            if(empty($user)) exception('找不到该用户!');
            $code = Input('post.code');
            if(empty($code)) exception('邀请码不能为空!');
            $invite = $this->field('id,level')->where(['invite_code'=>$code,'is_delete'=>0])->find();
            if(!$invite) exception('该用户不存在!');
            try{
                $model = new UserInvite();
                if($model->bindInviteTT($user,$invite)==false)
                    exception($model->error);
                $this->where(['id'=>$user->id])->update(['invite_id'=>$invite['id'],'binding_time'=>time()]);
                return true;
            }catch (\Exception $e){
                exception($e->getMessage());
            }
        }catch (\Exception $e){
            /*if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else*/ $this->error = $e->getMessage();
            return false;
        }
    }


    /*
     * 获取我的客户 头部数据
     */
    public function myCustomer($id){
        try{
            if(empty($id)) exception('找不到该用户!');
            $data = Input('post.');
            $where = ['uid' => $id,'is_delete'=>0];

            $invite = (new UserInvite())->where(['upid'=>$id])->field('uid')->select();
            $inv_num = [];
            //获取下级id
            if(!empty($invite)){
                $invite = array_column($invite->toArray(),'uid');
                $inv_num = array_unique($invite);
                $invite = implode(',',$inv_num);
            }
            if(empty($invite))
                $invite = $id;
            $field = "(consume+teams) as order_total,(select count(id) from `m3_order` where uid in ({$invite},{$id}) and status=5 and is_delete=0)+
                (select count(id) from `m3_user_volume` where uid in ({$invite},{$id}) and status=1 and is_delete=0) as order_number";

            $info = (new UserWallet())->where($where)->field($field)->find();
            if(!empty($info)){
                $info['order_total'] = getformat($info['order_total']);
                $info['invite_number'] = count($inv_num);
                unset($info['order_num']);
                unset($info['volume_num']);
            }else{
                $info['order_total'] = 0;
                $info['invite_number'] = 0;
            }
            #下级下单用户数
            if($invite == $id){
                $info['invite_order_num'] = 0;
            }else{
                //获取购物券和订单，根据用户分组
                $orderNum = (new Order())->where([['uid','in',$invite],['status','=',5],['is_delete','=',0]])->field('GROUP_CONCAT(uid) as order_num')->group('uid')->select();
                $volumeNum = (new UserVolume())->where([['uid','in',$invite],['status','=',1],['is_delete','=',0]])->field('GROUP_CONCAT(uid) as volume_num')->group('uid')->select();
                $order = '';$volume = '';
                if(!empty($orderNum)){
                    foreach($orderNum as $v) $order .= $v['order_num'].',';
                }
                if(!empty($volumeNum)){
                    foreach($volumeNum as $v) $volume .= $v['volume_num'].',';
                }
                $orderNum = trim($order,',');
                $volumeNum = rtrim($volume,',');
                $order = !empty($orderNum) ? explode(',',$orderNum) : [];
                $volume = !empty($volumeNum) ? explode(',',$volumeNum) : [];
                $info['invite_order_num'] = count(array_keys(array_flip($order)+array_flip($volume)));//2个数组去重后统计
            }
            $list = $this->myCustomerData($id);
            $info['list'] = $list;
            return $info;
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }


    /*
     * 获取我的客户 下级客户数据
     */
    public function myCustomerData($id){
        try{
            if(empty($id)) exception('找不到该用户!');
            $data = Input('post.');
            //查询条件
            $where[] = ['c.invite_id','=',$id];
            if(!empty($data['nickname'])) $where[] = ['c.nickname','like',trim($data['nickname']).'%'];
            if(isset($data['level'])&&!empty($data['level'])) $where[] = ['c.level','=',$data['level']];
            $where[] = ['c.is_delete','=',0];
            $limit = isset($data['limit'])&&!empty($data['limit']) ? $data['limit'] : 15;//每页显示数据
            $query = ['page' => (isset($data['page']) ? $data['page'] : 1)];//分页参数

            $field = "c.id,c.avatarurl,c.is_proceeds,c.nickname,c.level,c.binding_time,count(i.uid) as invite_number,in.consume as my_order_total,in.team_consume as invite_order_total,in.team_order_num as order_num,
                (select count(id) from `m3_order` where uid=c.id and status=5 and is_delete=0)+(select count(id) from `m3_user_volume` where uid=c.id and status=1 and is_delete=0) as my_order_num";
            $user = $this->alias('c')->join('user_info in','in.uid=c.id','left')->join('user_invite i','i.upid=c.id','left')->where($where)->field($field)->group('c.id')->order('c.binding_time desc')->paginate($limit, false, array('query'=>$query));

            $user->render();
            if(!empty($user)) {
                $level = (new UserLevel())->getList();//获取用户等级
                foreach ($level as $key => $val)
                    $levels[$val['id']] = $val['name'];
                $levels[0] = '游客';
                foreach ($user as $k => $v){
                    if($v['is_proceeds'] && $v['is_proceeds'] == 1 && $v['level'] == 1)
                        $user[$k]['level'] = 1;
                    else
                        $user[$k]['level'] =  $levels[$v['level']];
                    $user[$k]['order_num'] =  $v['order_num']?:0;
                    $user[$k]['invite_order_num'] =  $v['order_num']-$v['my_order_num'];
                    $user[$k]['order_total'] = getformat($v['my_order_total']+ $v['invite_order_total']);
                    $user[$k]['my_order_total'] = getformat($v['my_order_total']);
                    $user[$k]['invite_order_total'] = getformat($v['invite_order_total']);
                    $user[$k]['binding_time'] = date('Y-m-d H:i', $v['binding_time']);
                }
            }
            return $user;
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /**
     * 获取到当前用户层级， 并且可以拿去到模型操作
     *
     */

    /*
     * 获取下级数据
     */
    public function getInviteTop($id){
        return $this->alias('u')->join('user_invite i','u.id=i.uid','left')->where(['u.id'=>$id])->field('u.id,u.invite_id,i.top_id,i.upid,i.team_pid,i.pid')->find();
    }

    /*
     * 获取直属下级数量
     */
    public function getInviteNum($id){
        return $this->where(['invite_id'=>$id,'is_delete'=>0])->count();
    }


    /**
     * @param $user
     * @return array|bool|null|Model 返回关联当前用户层级模型
     */
    public function getLevel($user)
    {
        if($user && $user->level > 0) {
            $levelModel = (new UserLevel())->where('id', $user->level)->find();
            return $levelModel;
        }
        return false;
    }

    /**
     * 一对一关联
     * @return \think\model\relation\HasOne  返回关联当前用户层级模型
     */
    public function getLevelModel()
    {
        // 关联的用户层级表  用户层级表id,   当前字段
        return $this->hasOne(UserLevel::class,'id','level');
    }

    /**
     * 一对多关联
     * @return \think\model\relation\HasOne  返回关联当前用户层级模型
     */
    public function getAddersMany()
    {
        // 关联的用户层级表  用户层级表id,   当前字段
        return $this->hasMany(UserAddress::class,'uid','id');
    }


    /**
     * 将商品，视频，订单等 计算出当前的分享价格等
     * @param $list 需要传递过来的 data 数据
     * @return bool|array   返回false或者一个新的数组
     */
    public function getShareLevelData($list)
    {
        $bc =  new Bc();
        // 层级大于  等于0  且 当前有对应关联的层级模型 且 分享折扣大于0
        // 购物券vip用户专属 == 1
        if($this->level > 0 &&   ((isset($this->getLevelModel) && $this->getLevelModel->share > 0) || $this->is_proceeds == 1 ) ) {
            $data = [];
            // 只能是买了购物券且 用户层级为1
            $volume_share = 0;
            if($this->is_proceeds == 1 && $this->level == 1){
                $volumeConfig = (new Config)->getSrTypes('volumeVip');
                if($volumeConfig && isset($volumeConfig->share) && $volumeConfig->share > 0)$volume_share = $bc->calcDiv($volumeConfig->share, 10,2);
            }
            foreach ($list as $k => $v) {
                $share_money = 0;
                if($volume_share && $volume_share > 0){
                    $share_money = $bc->calcDiv($volume_share * $v['default_discount_price'],100,2);
                }else{
                    $share_money = $bc->calcDiv($this->getLevelModel->share * $v['default_discount_price'],100,2);
                }
                if($share_money && $share_money > 0) $v['share_money'] = $share_money;
                $data[] = $v;
            }
            return $data;
        }
        return false;
    }

    /*
     * 删除用户
     */
    public function test(){
        try{
            /*$id = Input('post.uid');
            if(empty($id)) exception('邀请码不能为空!');
            $user = $this->where(['id'=>$id])->delete();
            $wallet = (new UserWallet())->where(['uid'=>$id])->delete();
            $invite = (new UserInvite())->where(['uid'=>$id])->delete();*/
            return true;
        }catch (\Exception $e){
            if(stristr($e->getMessage(),'SQLSTATE')){
                $this->error = '数据走丢了，请稍后再试！';
            }else $this->error = $e->getMessage();
            return false;
        }
    }

    /**
     * 用户进行手机登录 操作
     */
    public function phoneLogin($phone,$code){
        $time = time();
        $token = createToken($phone.$code.$time);
        $user = $this::where('phone',$phone)->find();
        if($user){
            $redis = getRedis();
            $redis->set('token:'.$token,$user->id,3600 * 72);
            $user['token'] = $token;
            return retu_json(200,'登录成功',$user);
        }
        // 没有该用户 则创建
        $data = [
            'avatarurl' => 'https://miaommeis-1301812909.cos.ap-guangzhou.myqcloud.com/icon/%E7%BC%96%E7%BB%84%205%402x.png',
            'nickname' => '美妆说',
            'invite_code' => $this->getInvite(),
            'phone' => $phone,
            'openid' => '',
            'session_key' => '',
            'level' => 1,
            'token' => $token,
            'last_time' => $time,
            'add_time' => $time,
        ];
        $modelFlag = $this->insertGetId($data);
        if(!$modelFlag) exception('登录异常，请重新尝试！');
        $wallet = Db::name('user_wallet')->insertGetId(['uid'=>$modelFlag]);
        $info = Db::name('user_info')->insertGetId(['uid'=>$modelFlag, 'last_ip'=>$_SERVER['REMOTE_ADDR'], 'last_time'=>$time]);
        return retu_json(200,'注册成功，欢迎来的美妆说',$data);
    }
}
